﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EBookStore.Users;
using EBookStore.Payments;

namespace EBookStore.Orders
{
    class OrdersManager
    {
        List<Order> _orders;

        public List<Order> Orders { get { return _orders; } }
        private static OrdersManager _instance = null;
        private static object _syncObj = new object();

        /// <summary>
        /// Catalog instance
        /// </summary>
        public static OrdersManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_syncObj)
                    {
                        if (_instance == null)
                        {
                            _instance = new OrdersManager();
                        }
                    }
                }
                return _instance;
            }
        }


        private OrdersManager()
        {
            _orders = new List<Order>();
        }


        /// <summary>
        /// create new order for user, specifying payment, and list of books to order
        /// </summary>
        public Order CreateOrder(User u, eOrderVia eov, Payment p, SingleBookOrder[] sbos)
        {
            Order o = new Order(u, eov, p);
            o.AddBooks(sbos);

            return o;
        }
        
        /// <summary>
        /// Process user order ( charge money and order book(s) from publisher
        /// </summary>
        public void ProcessOrder(ref Order o)
        {
            if (!o.Payment.Charge())
            {
                throw new Exception("Cannot charge order");
            }
            o.Update(eOrderStatus.Charged);

            //todo: send publisher fax

            o.Update(eOrderStatus.ForwardedToPublisher);

        }
        /// <summary>
        /// cancel order if possible and do corresponding actions
        /// </summary>
        public void CancelOrder(ref Order o)
        {
            switch (o.Status)
            {
                case eOrderStatus.Created:
                    {
                        o.Cancel();
                        break;
                    }
                case eOrderStatus.Charged:
                case eOrderStatus.ForwardedToPublisher:
                    {
                        if (!o.Payment.Refund())
                        {
                            throw new Exception("Cannot refund");
                        }
                        o.Cancel();
                        break;

                    }
                case eOrderStatus.RecievedFromPublisher:
                    {
                        {
                            if (!o.Payment.Refund())
                            {
                                throw new Exception("Cannot refund");
                            }
                            //TODO: send book back to publisher
                            o.Cancel();
                            break;

                        }
                    }

                case eOrderStatus.SentToCustomer:
                case eOrderStatus.DeliveredToCustomer:
                    {
                        throw new Exception("Cannot Cancel, book is already sent/delivered to the customer");

                    }
                case eOrderStatus.Canceled:
                    {
                        throw new Exception("Order already canceled");
                    }
                default:
                    {
                        throw new Exception("Unkown status:'" + o.Status + "' can't cancel");
                    }
            }
        }

        /// <summary>
        /// return book back to EbookStore
        /// </summary>
        /// <param name="o"></param>
        public void ReturnOrder(ref Order o)
        {
            if (o.Status != eOrderStatus.DeliveredToCustomer)
            {
                throw new Exception("Cannot return book , it is not at customer");
            }
            //make sure user returns book
            //and refund him money
            if (!o.Payment.Refund())
            {
                throw new Exception("Cannot refund");
            }
            o.Update(eOrderStatus.ReturnedByCustomer);
            //send book back to publisher

        }

        /// <summary>
        /// Get all user's orders.
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public IEnumerable<Order> GetOrders(User user)
        {
            return (from el in _orders where el.User.ID.Equals(user.ID) select el).ToArray<Order>();
        }

        public IEnumerable<eOrderStatus> CheckOrderStatus(User u, int orderID)
        {
            return (from o in Orders where o.ID.Equals(orderID) && (u.GetType() == typeof(Clerk) ? true : u.ID == o.User.ID) select o.Status);
        }

        public IEnumerable<List<SingleBookOrder>> QueryPendingBooks()
        {
            return (from pb in OrdersManager.Instance.Orders
                    where pb.Status == eOrderStatus.ForwardedToPublisher ||
                        pb.Status == eOrderStatus.Charged
                    select pb.BookList);
        }
       
    }
}
